package main

import (
	"strconv"
	"fmt"
	"net/http"
	"os"
	"regexp"
)

var isEnd = make(chan int)

/**
最外层函数，用于循环开启协程抓取数据和接收管道消息退出协程
 */
func DoWork(start, end int)  {
	for i := start; i <= end; i++ {
		url := "https://www.pengfu.com/index_" + strconv.Itoa(i) + ".html"
		go getUrl(url, i)
	}

	for i := start; i <= end; i++ {
		fmt.Printf("第%d页抓取完毕\n", <- isEnd)
	}
}

/**
首先请求列表地址，抓取内页的URL，在请求内页URL抓取标题和文章
 */
func getUrl(url string, i int) {
	//抓取列表URL内容
	resp, err1 := http.Get(url)
	if err1 != nil {
		fmt.Println(err1)
		return
	}

	defer resp.Body.Close()

	//打开文件，准备写入数据
	fileName := "Pachong/Pa" + strconv.Itoa(i) + ".txt"
	f, err2 := os.Create(fileName)
	if err2 != nil {
		fmt.Println(err2)
		return
	}
	defer f.Close()

	//读取列表URL返回的内容
	buf := make([]byte, 1024 * 4)
	res := ""
	for  {
		n, _ := resp.Body.Read(buf)
		if n == 0 {
			//对内容进行正则匹配，只要内页URL
			res := regexps(res)
			num := 1
			for _, data := range res{
				f.Write([]byte("第" + strconv.Itoa(num) + "篇\n"))
				//请求抓取的内页URL，获取内容
				str := content(data[1])
				//正则抓取内页的标题和文章
				title, content, _ := regexpTC(str)
				for _, data1 := range title{
					ti := data1[1] + "\n"
					f.Write([]byte(ti))
				}
				for _, data1 := range content{
					co := data1[1] + "\n"
					f.Write([]byte(co))
				}
				f.Write([]byte("\n\n"))
				num++
			}
			isEnd <- i
			return
		}
		res += string(buf[:n])
	}
}

func regexps(data string) (url [][]string) {
	res := regexp.MustCompile(`<h1 class="dp-b"><a href="(?s:(.*?))"`)
	if res == nil {
		fmt.Println("err")
		url = nil
	}
	url = res.FindAllStringSubmatch(data, -1)
	return
}

func content(url string) (data string) {
	resp, err := http.Get(url)
	if err != nil {
		return
	}

	defer resp.Body.Close()

	buf := make([]byte, 1024 * 4)
	res := ""
	for {
		n, _ := resp.Body.Read(buf)
		if n == 0 {
			data = res
			return
		}
		res += string(buf[:n])
	}
}

func regexpTC(str string) (title [][]string, content [][]string, err error)  {
	//取出标题
	res := regexp.MustCompile(`<h1>(?s:(.*?))</h1>`)
	if res == nil {
		fmt.Println("err")
		//数据类型为error时，使用fmt.Errorf()
		err = fmt.Errorf("error")
	}
	//FindAllStringSubmatch 第二个参数是匹配次数，-1是无限匹配，其他数字是匹配指定的次数，这个页面h1有两个，我们只要第一个，所以
	//指定为1
	title = res.FindAllStringSubmatch(str, 1)

	//取出文章内容
	res_content := regexp.MustCompile(`<div class="content-txt pt10">(?s:(.*?))<a id="prev"`)
	if res_content == nil {
		fmt.Println("err")
		//数据类型为error时，使用fmt.Errorf()
		err = fmt.Errorf("error")
	}
	//文章内页具体内容也只匹配一次就可以了
	content = res_content.FindAllStringSubmatch(str, 1)
	return
}

func main() {
	var start, end int
	fmt.Println("请输入起始页码：")
	fmt.Scan(&start)
	fmt.Println("请输入结束页码：")
	fmt.Scan(&end)

	DoWork(start, end)
}
